<template>
  <section class="system-notification">
    <transition appear name="animate__animated animate__bounce" enter-active-class="animate__swing z-index-99"
      leave-active-class="animate__backOutRight">

      <section class="system-notification-bar" v-if="store.state.systemNotification.show">
        <section class="call-notification"
          v-show="store.state.systemNotification.showType===store.state.systemNotification.typeEnumeration.videoCallNotification">
          <section class="head-portrait-and-name">
            <nut-avatar icon="my" shape="square"></nut-avatar>
            <span class="name">{{callerId}}</span>
            <span>邀请您视频通话</span>
          </section>

          <section class="operation-bar">
            <nut-button @click="hangUp" size="mini">
              <svg class="icon" aria-hidden="true">
                <use xlink:href="#icon-guaduan"></use>
              </svg>
            </nut-button>

            <nut-animate type="ripple" loop>
              <nut-button @click="answer" size="mini">
                <svg class="icon" aria-hidden="true">
                  <use xlink:href="#icon-laidian"></use>
                </svg>
              </nut-button>
            </nut-animate>
          </section>
        </section>

        <section class="text-notification"
          v-show="store.state.systemNotification.showType===store.state.systemNotification.typeEnumeration.textNotification">
          <nut-animate type="shake" :loop="true">
            <nut-icon name="notice"></nut-icon>
          </nut-animate>

          <span>{{store.state.systemNotification.content}}</span>
          <nut-icon @click="closeSystemNotificationBar" class="close-icon" name="circle-close"></nut-icon>
        </section>
      </section>
    </transition>
  </section>

  <section>
    <router-view></router-view>
  </section>
</template>
  
<script setup>
import ReconnectingWebSocket from "reconnecting-websocket";
import Peer from "peerjs";
import { computed, onBeforeUnmount, onMounted } from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
const router = useRouter();
const store = useStore();

onMounted(() => {
  establishWebSocketConnection();
});

onBeforeUnmount(() => {
  releaseResources();
});

const callerId = computed(() => {
  if (store.state.systemNotification.showType === store.state.systemNotification.typeEnumeration.videoCallNotification) {
    const callerPeerId = store.state.dataConnection.callerDataConnection.peer;
    return callerPeerId.length > 7 ? callerPeerId.substring(0, 8).concat("...") : callerPeerId;
  }
  return undefined;
});

function releaseResources() {
  if (store.state.webSocket.webSocketConnection) {
    store.state.webSocket.webSocketConnection.close();
  }
  if (store.state.videoCall.localPeer) {
    store.state.videoCall.localPeer.destroy();
  }
}

function answer() {
  closeSystemNotificationBar();
  store.state.dataConnection.callerDataConnection.send({
    operationType: store.state.dataConnection.operationType.typeEnumeration.agreeCall,
    peerId: store.state.videoCall.localPeer.id
  });

  router.push({
    path: "/video-call-page", query: {
      videoCallType: store.state.videoCall.typeEnumeration.answer
    }
  });
}

function hangUp() {
  store.state.dataConnection.callerDataConnection.send({
    operationType: store.state.dataConnection.operationType.typeEnumeration.rejectCall,
    peerId: store.state.videoCall.localPeer.id
  });
  closeSystemNotificationBar();
}

function closeSystemNotificationBar() {
  store.state.systemNotification.show = false;
  store.state.systemNotification.showType = undefined;
}

function establishWebSocketConnection() {
  store.state.webSocket.webSocketConnection = new ReconnectingWebSocket("ws://localhost:9999/videoCallServerEndpoint");

  store.state.webSocket.webSocketConnection.onopen = () => {
    createPeerAndRegisterToWebSocketServer();
  };

  store.state.webSocket.webSocketConnection.onmessage = event => {
    console.log(event);
    parseWebSocketMessage(event.data);
  };
}

function parseWebSocketMessage(data) {
  const webSocketMessage = JSON.parse(data);
  console.log(webSocketMessage);

  if (webSocketMessage.type === store.state.webSocket.message.typeEnumeration.refreshPeerIds) {
    store.state.videoCall.peerIds.splice(0, store.state.videoCall.peerIds.length);
    store.state.videoCall.peerIds.push(...webSocketMessage.content);
    console.log(store.state.videoCall.peerIds);
  }
}


function createPeerAndRegisterToWebSocketServer() {
  const peer = new Peer();
  peer.on("open", localPeerId => {
    console.log("peer opend, the localPeerId is:", localPeerId);
    store.state.videoCall.localPeer = peer;

    peer.on("close", () => {
      console.log("peer close....");
      store.state.webSocket.webSocketConnection.send(JSON.stringify({
        type: store.state.webSocket.message.typeEnumeration.logOffPeer,
        content: localPeerId
      }));
    });


    peer.on("connection", dataConnection => {
      dataConnection.on("open", () => {
        store.state.dataConnection.callerDataConnection = dataConnection;
      });

      dataConnection.on("data", data => {
        console.log(data);
        if (data.operationType) {
          if (data.operationType === store.state.dataConnection.operationType.typeEnumeration.callRequest) {
            store.state.systemNotification.show = true;
            store.state.systemNotification.showType = store.state.systemNotification.typeEnumeration.videoCallNotification;
          } else if (data.operationType === store.state.dataConnection.operationType.typeEnumeration.hangUp) {
            console.log(data.operationType);
          }
        }
      });

    });

    store.state.webSocket.webSocketConnection.send(JSON.stringify({
      type: store.state.webSocket.message.typeEnumeration.registerPeer,
      content: localPeerId
    }));
    
  });
}

</script>

<style lang="scss" scoped>
.system-notification {
  position: sticky;
  z-index: 99;
  top: .5rem;

  .system-notification-bar {
    position: relative;

    .call-notification {
      position: absolute;
      display: flex;
      align-items: center;
      justify-content: space-between;
      min-height: 3.125rem;
      width: 100%;
      border-radius: .625rem;
      background-color: rgba(0, 0, 0, .8);

      .head-portrait-and-name {
        line-height: 100%;
        margin-left: .625rem;
        display: flex;
        align-items: center;
        color: white;
        font-size: .875rem;

        .name {
          color: red;
          margin-left: .3125rem;
        }
      }

      .operation-bar {
        line-height: 100%;
        margin-right: .625rem;

        >* {
          margin-right: .625rem;
        }
      }
    }

    .text-notification {
      position: absolute;
      display: flex;
      align-items: center;
      justify-content: space-around;
      z-index: 100;
      min-height: 3.125rem;
      width: 100%;
      border-radius: .625rem;
      background-color: rgba(0, 0, 0, .8);
      color: white;
    }
  }
}

.z-index-99 {
  z-index: 99;
}
</style>